﻿/*
 * @author rayzhang
 * @desc 事件路由/事件分发
 */
#pragma once
#include <QString>
#include <QVariant>
#include <QDebug>
namespace flow
{
template <typename Return, typename Payload>
class EventDispatcher : public QObject
{
public:
    using PayloadType = Payload;
    using ReturnType = Return;

    explicit EventDispatcher(QObject* parent = nullptr)
        : QObject(parent)
    {
        qDebug() << "created EventDispatcher " << this;
    }

    virtual ~EventDispatcher() { qDebug() << "deleted EventDispatcher " << this; }

    // 处理器
    using Handler     = std::function<ReturnType(PayloadType)>;
    using VoidHandler = std::function<void(PayloadType)>;
    // 路由映射表 - 规则
    using Routes = QMap<QString, Handler>;
    // 拦截器
    using RequestInterceptor = std::function<bool(const QString& key, PayloadType args)>;
    // using ResponseInterceptor = std::function<ReturnType(ReturnType, const QString& key, PayloadType args)>;

    void define(const QString& key, Handler handler) { _routesMap[key] = std::move(handler); }

    void remove(const QString& key)
    {
        if (_routesMap.contains(key)) {
            _routesMap.remove(key);
        }
    }

    [[nodiscard]] bool contains(const QString& key) const { return _routesMap.contains(key); }
    Handler handler(const QString& key) { return _routesMap.value(key); }

    ReturnType dispatch(const QString& key, PayloadType args = {})
    {
        bool skip = false;
        for (const auto& requestInterceptor : _requestInterceptors) {
            if (!requestInterceptor(key, args)) {
                skip = true;
                break;
            }
        }
        if (!skip && contains(key)) {
            return _routesMap[key](args);
        }
        if constexpr (!std::is_same_v<ReturnType, void>) {
            return {};
        }
        else {
            return;
        }
    }

    // 在事件分发之前的拦截器
    void addRequestInterceptor(const RequestInterceptor& interceptor)
    {
        //
        _requestInterceptors.push_back(interceptor);
    }

    // 事件处理完后
    // void addResponseInterceptor(const RequestInterceptor& interceptor) {
    // _responseInterceptors.push_back(interceptor); }

    // static std::unique_ptr<EventDispatcher>& instance()
    //{
    //     static std::unique_ptr<EventDispatcher> d{std::make_unique<EventDispatcher>()};
    //     return d;
    // }

protected:
    Routes _routesMap;

    QList<RequestInterceptor> _requestInterceptors;
    // QList<ResponseInterceptor> _responseInterceptors;
};

} // namespace cq
